package com.yami.shop.nft.common.service.impl;

import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yami.shop.bean.dto.AsyncAddCoinDTO;
import com.yami.shop.bean.dto.AsyncCoinDTO;
import com.yami.shop.bean.model.ProdNft;
import com.yami.shop.common.bean.PageDTO;
import com.yami.shop.common.bean.PageVO;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.util.PageUtil;
import com.yami.shop.nft.common.dao.NftApplyImgMapper;
import com.yami.shop.nft.common.dao.NftApplyMapper;
import com.yami.shop.nft.common.dao.NftDawMapper;
import com.yami.shop.nft.common.dao.NftDenomMapper;
import com.yami.shop.nft.common.dto.NftDenomDto;
import com.yami.shop.nft.common.model.NftApply;
import com.yami.shop.nft.common.model.NftApplyImg;
import com.yami.shop.nft.common.model.NftDaw;
import com.yami.shop.nft.common.model.NftDenom;
import com.yami.shop.nft.common.service.NftApplyService;
import com.yami.shop.nft.common.service.NftDawService;
import com.yami.shop.nft.common.service.NftDenomService;
import com.yami.shop.nft.common.vo.NftVO;
import com.yami.shop.service.ProdNftService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

@Service
@Slf4j
public class NftDawServiceImpl extends ServiceImpl<NftDawMapper, NftDaw> implements NftDawService {

    @Autowired
    private NftApplyMapper nftApplyMapper;
    @Autowired
    private NftApplyImgMapper nftApplyImgMapper;
    @Autowired
    private NftDawMapper nftDawMapper;
    @Autowired
    private NftDenomMapper nftDenomMapper;
    @Autowired
    private NftDenomService nftDenomService;
    @Autowired
    private NftApplyService nftApplyService;
    @Autowired
    private ProdNftService prodNftService;
    @Override
    public PageVO<NftVO> pageNftDaw(PageDTO pageDTO, String nftName, String denomId, Integer sysType, Long shopId) {

        List<String> denomIds = new ArrayList<>();
        // 店铺端
        PageVO<NftVO> page = new PageVO<>();
        if (sysType == 1) {
            denomIds = nftDenomMapper.getDenomIds(shopId);
            if (ObjectUtils.isEmpty(denomIds)) {
                return page;
            }
        }
        List<String> finalDenomIds = denomIds;
        page = PageUtil.doPage(pageDTO, () -> nftDawMapper.selectDawNameList(nftName, denomId, finalDenomIds));
        return page;
    }

    @Override
    public void MintsNftDawNew(Integer applyId) {
        // 查询申请材料信息
        LambdaQueryWrapper<NftApply> nftApplyLambdaQueryWrapper = new LambdaQueryWrapper<NftApply>().eq(NftApply::getId, applyId);
        NftApply nftApplyById = nftApplyMapper.selectOne(nftApplyLambdaQueryWrapper);
        if (ObjectUtils.isEmpty(nftApplyById)) {
            throw new YamiShopBindException("申请信息异常");
        }
        LambdaQueryWrapper<NftDenom> eq = new LambdaQueryWrapper<NftDenom>().eq(NftDenom::getDenomId, nftApplyById.getDenomId());
        List<NftDenom> nftDenoms = nftDenomMapper.selectList(eq);
        if (ObjectUtils.isEmpty(nftDenoms)) {
            throw new YamiShopBindException("获取类别信息异常");
        }
        List<NftDaw> nftDawsList = new ArrayList<>();
        // 添加daw附属表信息
        for (int i = 0; i < nftApplyById.getNftNum(); i++) {
            String dawId = "daw" + IdUtil.simpleUUID();
            String operationId = "dtc" + IdUtil.simpleUUID();
            NftDaw nftDaw = new NftDaw();
            nftDaw.setNftApplyId(nftApplyById.getId());
            nftDaw.setDenomId(nftApplyById.getDenomId());
            if (nftDenoms.get(0).getBlockchainCode().equals("avata")) {
                nftDaw.setOperationId(operationId);
            } else if (nftDenoms.get(0).getBlockchainCode().equals("szavata")) {
                nftDaw.setOperationId(operationId);
                nftDaw.setNftCode(String.format("%05d", i + 1));
            } else if (nftDenoms.get(0).getBlockchainCode().equals("hw")) {
                nftDaw.setDawId(String.valueOf(i + 1));
                nftDaw.setNftCode(String.format("%05d", i + 1));
            } else {
                nftDaw.setDawId(dawId);
                nftDaw.setNftCode(String.format("%05d", i + 1));
            }
            nftDaw.setBlockchainCode(nftDenoms.get(0).getBlockchainCode());
            nftDaw.setUseStatus(0);
            nftDaw.setChainUpStatus(2);
            nftDaw.setCreateTime(new Date());
            nftDawsList.add(nftDaw);
        }
        saveBatch(nftDawsList);
        NftApply updateNftApply = new NftApply();
        updateNftApply.setId(nftApplyById.getId());
        // 修改铸币状态
        updateNftApply.setMintStatus(1);
        nftApplyMapper.updateById(updateNftApply);
    }

    @Override
    public void addToMintsNftDawNew(Integer applyId) {
        // 查询申请材料信息
        NftApply nftApplyById = nftApplyMapper.getNftApplyAndImgInfo(applyId.longValue());
        // 查询最后一个币的编码
        QueryWrapper<NftDaw> wrapper = new QueryWrapper<>();
        wrapper.eq("denom_id",nftApplyById.getDenomId());
        wrapper.orderByDesc("nft_code+0");
        wrapper.last("limit 1");
        //分页
        NftDaw one = nftDawMapper.selectOne(wrapper);
        List<NftDaw> nftDawsList = new ArrayList<>();
        // 添加daw附属表信息
        for (int i = 0; i < nftApplyById.getNftNum(); i++) {
            String dawId = "daw" + IdUtil.simpleUUID();
            String operationId = "dtc" + IdUtil.simpleUUID();
            NftDaw nftDaw = new NftDaw();
            nftDaw.setNftApplyId(nftApplyById.getId());
            nftDaw.setDenomId(nftApplyById.getDenomId());
            if (one.getBlockchainCode().equals("avata")) {
                nftDaw.setOperationId(operationId);
            } else if (one.getBlockchainCode().equals("szavata")) {
                nftDaw.setOperationId(operationId);
                nftDaw.setNftCode(String.format("%05d", Integer.valueOf(one.getNftCode()) + i + 1));
            } else if (one.getBlockchainCode().equals("hw")) {
                nftDaw.setDawId(String.valueOf(Integer.valueOf(one.getDawId()) + i + 1));
                nftDaw.setNftCode(String.format("%05d", Integer.valueOf(one.getNftCode()) + i + 1));
            } else {
                nftDaw.setDawId(dawId);
                nftDaw.setNftCode(String.format("%05d", Integer.valueOf(one.getNftCode()) + i + 1));
            }
            nftDaw.setBlockchainCode(nftApplyById.getRemarks());
            nftDaw.setUseStatus(0);
            nftDaw.setChainUpStatus(2);
            nftDaw.setCreateTime(new Date());
            nftDawsList.add(nftDaw);
        }
        saveBatch(nftDawsList);
        NftApply updateNftApply = new NftApply();
        updateNftApply.setId(nftApplyById.getId());
        // 修改铸币状态
        updateNftApply.setMintStatus(1);
        nftApplyMapper.updateById(updateNftApply);
    }

    @Override
    public List<NftDaw> selectDawListLimit(String denomId, Integer num) {
        return nftDawMapper.selectDawListLimit(denomId, num);
    }

    @Override
    @Transactional
    public String asynCoin(AsyncCoinDTO asyncCoinDTO) {
        //创建分类
        LambdaQueryWrapper<NftDenom> nftDenomLambdaQueryWrapper = new LambdaQueryWrapper<>();
        nftDenomLambdaQueryWrapper.eq(NftDenom::getDenomName,asyncCoinDTO.getProdName()).eq(NftDenom::getShopId,asyncCoinDTO.getShopId()).last("limit 1");
        NftDenom nftDenom = nftDenomMapper.selectOne(nftDenomLambdaQueryWrapper);

        if(Objects.isNull(nftDenom)){
            NftDenomDto nftDenomDto = new NftDenomDto();
            nftDenomDto.setShopId(asyncCoinDTO.getShopId());
            nftDenomDto.setBlockchainCode("dt");
            nftDenomDto.setDenomName(asyncCoinDTO.getProdName());
            nftDenom = nftDenomService.insertDenom(nftDenomDto);
        }
        NftApply nftApplyAndImgInfoByDenomIdAndStatus = nftApplyService.getNftApplyAndImgInfoByDenomIdAndStatus(nftDenom.getDenomId());
        if(!Objects.isNull(nftApplyAndImgInfoByDenomIdAndStatus)){
            log.info("已经有铸币申请信息了");
            throw new YamiShopBindException("已经申请过铸币了");
        }
        //铸币
        NftApply nftApply = new NftApply();
        nftApply.setParentId(0);
        nftApply.setMintStatus(2);
        nftApply.setMintType(0);
        nftApply.setApplyStatus(2);
        nftApply.setDenomId(nftDenom.getDenomId());
        nftApply.setNftNum(asyncCoinDTO.getApplyNum());
        nftApply.setShopId(asyncCoinDTO.getShopId());
        nftApply.setNftName(asyncCoinDTO.getProdName());
        nftApply.setRemarks(nftDenom.getBlockchainCode());
        nftApplyMapper.insert(nftApply);
        NftApplyImg nftApplyImg = new NftApplyImg();
        nftApplyImg.setImgType(1);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("sourceFile",asyncCoinDTO.getPicUrl());
        jsonObject.put("cloudRenderingId","");
        jsonObject.put("modelMtl","");
        jsonObject.put("modelJpg","");
        if(asyncCoinDTO.getIsReplaceUrl() == 1){
            jsonObject.put("sourceUrlPdf","/cqdj.pdf");
        }
        nftApplyImg.setImgUrl(jsonObject.toJSONString());
        nftApplyImg.setImgThumbnail(asyncCoinDTO.getPicUrl());
        nftApplyImg.setImgName(asyncCoinDTO.getProdName());
        nftApplyImg.setApplyId(nftApply.getId().intValue());
        nftApplyImg.setIsReplaceUrl(asyncCoinDTO.getIsReplaceUrl());
        nftApplyImgMapper.insert(nftApplyImg);

        List<NftDaw> nftDawsList = new ArrayList<>();
        // 添加daw附属表信息
        for (int i = 0; i < asyncCoinDTO.getApplyNum(); i++) {
            NftDaw nftDaw = new NftDaw();
            nftDaw.setNftApplyId(nftApply.getId());
            nftDaw.setDenomId(nftDenom.getDenomId());
            nftDaw.setNftCode(String.format("%05d", i + 1));
            nftDaw.setBlockchainCode("dt");
            nftDaw.setUseStatus(0);
            nftDaw.setChainUpStatus(2);//预铸币
            nftDaw.setCreateTime(new Date());
            String dawId = "daw" + IdUtil.simpleUUID();
            nftDaw.setDawId(dawId);
            nftDawsList.add(nftDaw);
        }
        saveBatch(nftDawsList);
        return nftDenom.getDenomId();
    }
    @Override
    public synchronized void asyncAddCoin(AsyncAddCoinDTO asyncAddCoinDTO) {
        if(StrUtil.isNotEmpty(asyncAddCoinDTO.getPrefixCode())){
            String prefixCode = StrUtil.subPre(asyncAddCoinDTO.getPrefixCode(), 1);
            if(!Validator.isLowerCase(prefixCode)){
                throw new YamiShopBindException("编码必须以小写字母开头");
            }
        }
        ProdNft dataByProdId = prodNftService.getDataByProdId(asyncAddCoinDTO.getProdId());
        LambdaQueryWrapper<NftDaw> nftDenomLambdaQueryWrapper = new LambdaQueryWrapper<>();
        nftDenomLambdaQueryWrapper.eq(NftDaw::getDenomId,dataByProdId.getDenomId()).isNull(NftDaw::getDawId).last("limit "+asyncAddCoinDTO.getApplyNum());
        List<NftDaw> nftDaws = nftDawMapper.selectList(nftDenomLambdaQueryWrapper);
        if(nftDaws.isEmpty()){
            throw new YamiShopBindException("没有可激活的币");
        }
        if(nftDaws.size()< asyncAddCoinDTO.getApplyNum()){
            throw new YamiShopBindException("可激活币数量不足");
        }
        for (NftDaw nftDaw : nftDaws) {
            String prefix = StrUtil.isEmpty(asyncAddCoinDTO.getPrefixCode()) ? "daw" : asyncAddCoinDTO.getPrefixCode() ;
            nftDaw.setDawId(prefix + IdUtil.simpleUUID());
            nftDaw.setUpdateTime(new Date());
        }
        updateBatchById(nftDaws);
    }

    @Override
    public Long asyncIsHaveCoin(Long prodId, Integer useStatus,String prefixCode,Boolean hasPreparingChain) {
        ProdNft dataByProdId = prodNftService.getDataByProdId(prodId);
        LambdaQueryWrapper<NftDaw> nftDenomLambdaQueryWrapper = new LambdaQueryWrapper<>();
        nftDenomLambdaQueryWrapper.eq(NftDaw::getDenomId,dataByProdId.getDenomId()).likeRight(StrUtil.isNotEmpty(prefixCode),NftDaw::getDawId,prefixCode).eq(useStatus!=null, NftDaw::getUseStatus,useStatus);
        if(hasPreparingChain){
            nftDenomLambdaQueryWrapper.in(NftDaw::getChainUpStatus,2,4).isNotNull(NftDaw::getDawId);
        }else{
            nftDenomLambdaQueryWrapper.eq(NftDaw::getChainUpStatus,2);
        }
        return nftDawMapper.selectCount(nftDenomLambdaQueryWrapper);
    }
}
